package com.cencat.order.dto;

import com.fasterxml.jackson.annotation.JsonFormat;
import jakarta.validation.constraints.*;
import lombok.Data;
import lombok.experimental.Accessors;

import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;

/**
 * 智能派单数据传输对象
 * 
 * @author cencat
 * @date 2024-01-20
 */
@Data
@Accessors(chain = true)
public class DispatchDTO implements Serializable {

    private static final long serialVersionUID = 1L;

    /**
     * 派单ID(更新时必填)
     */
    private Long dispatchId;

    /**
     * 派单编号
     */
    @Size(max = 50, message = "派单编号长度不能超过50个字符")
    private String dispatchCode;

    /**
     * 订单ID
     */
    @NotNull(message = "订单ID不能为空")
    private Long orderId;

    /**
     * 订单编号
     */
    @Size(max = 50, message = "订单编号长度不能超过50个字符")
    private String orderCode;

    /**
     * 路线ID
     */
    private Long routeId;

    /**
     * 路线编号
     */
    @Size(max = 50, message = "路线编号长度不能超过50个字符")
    private String routeCode;

    /**
     * 司机ID
     */
    private Long driverId;

    /**
     * 司机编号
     */
    @Size(max = 50, message = "司机编号长度不能超过50个字符")
    private String driverCode;

    /**
     * 车辆ID
     */
    private Long vehicleId;

    /**
     * 车牌号
     */
    @Size(max = 20, message = "车牌号长度不能超过20个字符")
    private String vehiclePlateNumber;

    /**
     * 商家ID
     */
    private Long merchantId;

    /**
     * 商家编号
     */
    @Size(max = 50, message = "商家编号长度不能超过50个字符")
    private String merchantCode;

    /**
     * 派单类型(1-自动派单 2-手动派单 3-抢单模式 4-指定派单)
     */
    @NotNull(message = "派单类型不能为空")
    @Min(value = 1, message = "派单类型值不正确")
    @Max(value = 4, message = "派单类型值不正确")
    private Integer dispatchType;

    /**
     * 派单方式(1-距离优先 2-时间优先 3-成本优先 4-综合优先)
     */
    @NotNull(message = "派单方式不能为空")
    @Min(value = 1, message = "派单方式值不正确")
    @Max(value = 4, message = "派单方式值不正确")
    private Integer dispatchMethod;

    /**
     * 派单状态(0-待派单 1-已派单 2-已接单 3-已拒单 4-派单超时 5-派单取消)
     */
    @Min(value = 0, message = "派单状态值不正确")
    @Max(value = 5, message = "派单状态值不正确")
    private Integer dispatchStatus;

    /**
     * 优先级(1-低 2-中 3-高 4-紧急)
     */
    @Min(value = 1, message = "优先级值不正确")
    @Max(value = 4, message = "优先级值不正确")
    private Integer priority;

    /**
     * 紧急程度(1-普通 2-加急 3-特急)
     */
    @Min(value = 1, message = "紧急程度值不正确")
    @Max(value = 3, message = "紧急程度值不正确")
    private Integer urgencyLevel;

    /**
     * 货物名称
     */
    @Size(max = 200, message = "货物名称长度不能超过200个字符")
    private String goodsName;

    /**
     * 货物类型
     */
    @Size(max = 50, message = "货物类型长度不能超过50个字符")
    private String goodsType;

    /**
     * 货物重量(公斤)
     */
    @DecimalMin(value = "0.1", message = "货物重量不能小于0.1公斤")
    private BigDecimal goodsWeight;

    /**
     * 货物体积(立方米)
     */
    @DecimalMin(value = "0.01", message = "货物体积不能小于0.01立方米")
    private BigDecimal goodsVolume;

    /**
     * 货物数量
     */
    @Min(value = 1, message = "货物数量不能小于1")
    private Integer goodsQuantity;

    /**
     * 货物价值
     */
    @DecimalMin(value = "0.0", message = "货物价值不能小于0")
    private BigDecimal goodsValue;

    /**
     * 特殊要求
     */
    @Size(max = 500, message = "特殊要求长度不能超过500个字符")
    private String specialRequirements;

    /**
     * 取货地址
     */
    @NotBlank(message = "取货地址不能为空")
    @Size(max = 200, message = "取货地址长度不能超过200个字符")
    private String pickupAddress;

    /**
     * 取货联系人
     */
    @Size(max = 50, message = "取货联系人长度不能超过50个字符")
    private String pickupContactPerson;

    /**
     * 取货联系电话
     */
    @Pattern(regexp = "^1[3-9]\\d{9}$", message = "取货联系电话格式不正确")
    private String pickupContactPhone;

    /**
     * 配送地址
     */
    @NotBlank(message = "配送地址不能为空")
    @Size(max = 200, message = "配送地址长度不能超过200个字符")
    private String deliveryAddress;

    /**
     * 配送联系人
     */
    @Size(max = 50, message = "配送联系人长度不能超过50个字符")
    private String deliveryContactPerson;

    /**
     * 配送联系电话
     */
    @Pattern(regexp = "^1[3-9]\\d{9}$", message = "配送联系电话格式不正确")
    private String deliveryContactPhone;

    /**
     * 预计距离(公里)
     */
    @DecimalMin(value = "0.1", message = "预计距离不能小于0.1公里")
    private BigDecimal estimatedDistance;

    /**
     * 预计时长(分钟)
     */
    @Min(value = 1, message = "预计时长不能小于1分钟")
    private Integer estimatedDuration;

    /**
     * 预计费用
     */
    @DecimalMin(value = "0.0", message = "预计费用不能小于0")
    private BigDecimal estimatedFee;

    /**
     * 实际距离(公里)
     */
    @DecimalMin(value = "0.0", message = "实际距离不能小于0")
    private BigDecimal actualDistance;

    /**
     * 实际时长(分钟)
     */
    @Min(value = 0, message = "实际时长不能小于0分钟")
    private Integer actualDuration;

    /**
     * 实际费用
     */
    @DecimalMin(value = "0.0", message = "实际费用不能小于0")
    private BigDecimal actualFee;

    /**
     * 派单时间
     */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime dispatchTime;

    /**
     * 接单时间
     */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime acceptTime;

    /**
     * 拒单时间
     */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime rejectTime;

    /**
     * 超时时间
     */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime timeoutTime;

    /**
     * 取消时间
     */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime cancelTime;

    /**
     * 完成时间
     */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime completeTime;

    /**
     * 算法版本
     */
    @Size(max = 20, message = "算法版本长度不能超过20个字符")
    private String algorithmVersion;

    /**
     * 匹配得分
     */
    @DecimalMin(value = "0.0", message = "匹配得分不能小于0")
    @DecimalMax(value = "100.0", message = "匹配得分不能大于100")
    private BigDecimal matchScore;

    /**
     * 派单规则
     */
    @Size(max = 500, message = "派单规则长度不能超过500个字符")
    private String dispatchRules;

    /**
     * 重试次数
     */
    @Min(value = 0, message = "重试次数不能小于0")
    @Max(value = 10, message = "重试次数不能大于10")
    private Integer retryCount;

    /**
     * 最大重试次数
     */
    @Min(value = 1, message = "最大重试次数不能小于1")
    @Max(value = 10, message = "最大重试次数不能大于10")
    private Integer maxRetryCount;

    /**
     * 超时时长(分钟)
     */
    @Min(value = 1, message = "超时时长不能小于1分钟")
    @Max(value = 1440, message = "超时时长不能大于1天")
    private Integer timeoutDuration;

    /**
     * 超时原因
     */
    @Size(max = 200, message = "超时原因长度不能超过200个字符")
    private String timeoutReason;

    /**
     * 异常信息
     */
    @Size(max = 500, message = "异常信息长度不能超过500个字符")
    private String exceptionInfo;

    /**
     * 处理人ID
     */
    private Long handlerId;

    /**
     * 处理人姓名
     */
    @Size(max = 50, message = "处理人姓名长度不能超过50个字符")
    private String handlerName;

    /**
     * 处理时间
     */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime handleTime;

    /**
     * 处理备注
     */
    @Size(max = 500, message = "处理备注长度不能超过500个字符")
    private String handleRemark;

    /**
     * 评价分数(1-5分)
     */
    @Min(value = 1, message = "评价分数不能小于1分")
    @Max(value = 5, message = "评价分数不能大于5分")
    private Integer ratingScore;

    /**
     * 评价内容
     */
    @Size(max = 500, message = "评价内容长度不能超过500个字符")
    private String ratingContent;

    /**
     * 评价时间
     */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime ratingTime;

    /**
     * 备注
     */
    @Size(max = 500, message = "备注长度不能超过500个字符")
    private String remark;

    /**
     * 扩展字段1
     */
    @Size(max = 200, message = "扩展字段1长度不能超过200个字符")
    private String extField1;

    /**
     * 扩展字段2
     */
    @Size(max = 200, message = "扩展字段2长度不能超过200个字符")
    private String extField2;

    /**
     * 扩展字段3
     */
    @Size(max = 200, message = "扩展字段3长度不能超过200个字符")
    private String extField3;

    /**
     * 候选司机列表
     */
    private List<CandidateDriverDTO> candidateDrivers;

    /**
     * 派单历史记录
     */
    private List<DispatchHistoryDTO> dispatchHistories;

    /**
     * 候选司机数据传输对象
     */
    @Data
    @Accessors(chain = true)
    public static class CandidateDriverDTO implements Serializable {

        private static final long serialVersionUID = 1L;

        /**
         * 司机ID
         */
        @NotNull(message = "司机ID不能为空")
        private Long driverId;

        /**
         * 司机编号
         */
        private String driverCode;

        /**
         * 司机姓名
         */
        private String driverName;

        /**
         * 司机手机号
         */
        private String driverPhone;

        /**
         * 匹配得分
         */
        @DecimalMin(value = "0.0", message = "匹配得分不能小于0")
        @DecimalMax(value = "100.0", message = "匹配得分不能大于100")
        private BigDecimal matchScore;

        /**
         * 距离(公里)
         */
        @DecimalMin(value = "0.0", message = "距离不能小于0")
        private BigDecimal distance;

        /**
         * 预计到达时间(分钟)
         */
        @Min(value = 0, message = "预计到达时间不能小于0分钟")
        private Integer estimatedArrivalTime;

        /**
         * 司机状态(0-离线 1-空闲 2-忙碌 3-休息)
         */
        @Min(value = 0, message = "司机状态值不正确")
        @Max(value = 3, message = "司机状态值不正确")
        private Integer driverStatus;

        /**
         * 车辆类型
         */
        private String vehicleType;

        /**
         * 载重能力(吨)
         */
        @DecimalMin(value = "0.1", message = "载重能力不能小于0.1吨")
        private BigDecimal loadCapacity;

        /**
         * 推荐原因
         */
        @Size(max = 200, message = "推荐原因长度不能超过200个字符")
        private String recommendReason;
    }

    /**
     * 派单历史记录数据传输对象
     */
    @Data
    @Accessors(chain = true)
    public static class DispatchHistoryDTO implements Serializable {

        private static final long serialVersionUID = 1L;

        /**
         * 历史记录ID
         */
        private Long historyId;

        /**
         * 操作类型(1-派单 2-接单 3-拒单 4-超时 5-取消)
         */
        @NotNull(message = "操作类型不能为空")
        @Min(value = 1, message = "操作类型值不正确")
        @Max(value = 5, message = "操作类型值不正确")
        private Integer operationType;

        /**
         * 操作时间
         */
        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
        private LocalDateTime operationTime;

        /**
         * 操作人ID
         */
        private Long operatorId;

        /**
         * 操作人姓名
         */
        private String operatorName;

        /**
         * 操作描述
         */
        @Size(max = 200, message = "操作描述长度不能超过200个字符")
        private String operationDesc;

        /**
         * 备注
         */
        @Size(max = 200, message = "备注长度不能超过200个字符")
        private String remark;
    }
}